/*
 * main.cpp
 *
 *  Created on: Sep 2, 2012
 *      Author: m
 */

#include <iostream>
#include <fstream>
#include <algorithm>
#include <cstring>
#include <string>
#include <cassert>
#include <cstdlib>
#include <sstream>
#include "logic_layer/external_sort/DictionaryTermsFile.h"
#include "logic_layer/external_sort/tools/Heap.h"
#include "logic_layer/external_sort/ExternalSort.h"

#define STRING_MAX_SIZE 40

using namespace std;

size_t bufferSize = 100;
bool outputInteger = false;

void invalid_args() {
	std::cerr << "Argumentos inválidos. " << std::endl
			<< "Uso: sortApp dictionaryFileName sortedFileName [-n nsize -i]"
			<< std::endl;
	exit(1);
}

void parseArgs(int argc, char* argv[]) {

	for (int i = 3; i < argc; ++i) {
		if (strcmp(argv[i], "-n") == 0) {
			bufferSize = (size_t) atoi(argv[i + 1]);
			i++;
			continue;
		}
		if (strcmp(argv[i], "-i") == 0) {
			outputInteger = true;
			continue;
		}
	}
}

int main(int argc, char* argv[]) {

	if (argc < 3) {
		invalid_args();
	}

	parseArgs(argc, argv);

	string dictionaryInput = argv[1];
	string sortInput = string(argv[1]) + ".random.bin";
	string sortOutput = argv[2];
	string txtOutput = string(argv[2]) + ".txt";

	try {

		DictionaryTermsFile BinaryDictionary(sortInput.c_str(),
				ios_base::out | ios_base::trunc, bufferSize, bufferSize, true);

		srand(24);
		ifstream infile(dictionaryInput.c_str());
		ofstream txtStream(txtOutput.c_str());
		string buffer;
		int random;
		int count = 0;

		while (infile >> buffer) {
			// Asigno un random
			random = rand();

			// Leo la palabra y la copio en un cstring para evitar problemas de acceso inválido a memoria cuando escriba de a STRING_MAX_SIZE characteres.
			assert( buffer.length()<STRING_MAX_SIZE);

			count++;
			std::unique_ptr<DictionaryTerm> term(
					new DictionaryTerm(buffer.c_str(), random, count));
			BinaryDictionary.put(term.get());
		}

		infile.close();

		BinaryDictionary.close();

		ExternalSort sorter(bufferSize, sortInput, sortOutput, outputInteger);
		sorter.sort();

		cout << endl << "Sort Output:" << endl;
		DictionaryTermsFile SortedBinaryDictionary(sortOutput.c_str(),
				ios_base::in, bufferSize, bufferSize, outputInteger);

		int count2 = 0;
		while (SortedBinaryDictionary.hasNext()) {
			count2++;
			std::shared_ptr<DictionaryTerm> term = SortedBinaryDictionary.get();
			txtStream << term->getTerm() << endl;
//			cout << term->getTerm() << ":\t\t" << term->getRandomKey() << endl;
		}

		SortedBinaryDictionary.close();

		cout << endl << "cantidad salida final:" << count2 << endl;

	} catch (string *e) {
		cout << "\n\n----------------\nException Thrown:" << *e
				<< "\n----------------\n\n";
		delete e;
	}

	return 0;
}

